package com.hp.bon.sgw.core.channel;

import cn.chinatelecom.sgw.soap.SgwQueryReq;
import com.hp.bon.sgw.bean.ProtocalConvertResult;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.convert.DataExchangerImpl;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.core.channel.handler.SCSPAsynCallHandler;
import com.hp.bon.sgw.domain.Node;
import com.hp.bon.sgw.domain.SGWChannel;
import com.hp.bon.sgw.scsp.FieldNotExistException;
import com.hp.bon.sgw.scsp.SCSPMessage;
import com.hp.bon.sgw.scsp.SCSPUtils;
import com.hp.bon.sgw.scsp.SessionHandler;
import com.hp.bon.sgw.util.Comutils;
import com.hp.bon.sgw.util.dcc.DccAvpHelper;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.Message;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.List;
import org.apache.mina.core.session.IoSession;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SCSPChannel extends SessionHandler
  implements IChannel
{
  private SCSPAsynCallHandler asynCallHandler;
  private static final Logger logger = LoggerFactory.getLogger(SCSPChannel.class);
  String hostId;
  String scspURL;

  protected void handleCLR(IoSession session, Element root)
  {
	InetSocketAddress addreass;
    String attrMID = "";
    String attrUserName = "";
    String attrPassword = "";
    int returnCode = 0;
    String ds = "SUCCESS";
    String hostId = "";
    try
    {
      attrMID = SCSPUtils.parseField(root, "MID", true);
      attrUserName = SCSPUtils.parseField(root, "UID", true);
      attrPassword = SCSPUtils.parseField(root, "PWD", true);
      returnCode = 0;
      addreass = (InetSocketAddress)session.getRemoteAddress();
    }
    catch (FieldNotExistException e)
    {
      returnCode = 11104;
      ds = "Field: " + e.getFieldName() + " is not exist";
    }
    Element rootCLA = DocumentHelper.createElement("CLA");
    rootCLA.addAttribute("MID", attrMID);
    rootCLA.addAttribute("RC", String.valueOf(returnCode));
    SCSPUtils.addElement(rootCLA, "DS", ds);
    sendMsg(session, rootCLA);

    if (returnCode == 0) {
      onConnectionReady(hostId, session);
      session.setAttribute("HOST_ID", hostId);
      session.setAttribute("PASSWORD", attrPassword);
    }
    else {
      closeSocket(session, ds, returnCode);
    }
  }

  public void handleSCR(IoSession session, Element root) {
    XmlMessage sgwQueryReq = new XmlMessage(true);
    String attrMID = "";
    String attrREPTAG = "";
    String attrSCID = "";
    String attrDATA = "";
    String attrSIG = "";
    String ds = "";
    try {
      attrMID = SCSPUtils.parseField(root, "MID", true);
      attrREPTAG = SCSPUtils.parseField(root, "REPTAG", false);
      attrSCID = SCSPUtils.parseField(root, "SCID", true);
      attrSIG = root.elementText("SIG");
      Element data = (Element)root.element("DATA").elements().get(0);
      if (data == null) {
        throw new FieldNotExistException("DATA");
      }
      sgwQueryReq.setDATA(data.asXML());
      sgwQueryReq.setUID((String)session.getAttribute("HOST_ID"));
      sgwQueryReq.setMID(attrMID);
      sgwQueryReq.setSCID(attrSCID);
      sgwQueryReq.setSIG(attrSIG == null ? "" : attrSIG);

      StringBuilder hint = new StringBuilder();
      this.asynCallHandler = new SCSPAsynCallHandler(session, this);
      CallParam callParam = new CallParam(attrMID, attrSCID, sgwQueryReq, sgwQueryReq.getUID(), this.asynCallHandler);
      int checkCode = BuzProcessorManager.getInstance().checkBonCallParamForSoap(callParam, hint);
      logger.warn("result:"+checkCode);
      if (checkCode != 0) {
        callParam.setRetCode(checkCode);
        callParam.setResultMsg(hint.toString());
        this.asynCallHandler.onCallResult(callParam);
        return;
      }
      BuzProcessorManager.getInstance().processRequest(callParam);
    }
    catch (FieldNotExistException e) {
      ds = "Filed: " + e.getFieldName() + " is not exist";
      logger.warn(ds);
      Element rootSCA = DocumentHelper.createElement("SCA");
      rootSCA.addAttribute("MID", attrMID);
      rootSCA.addAttribute("REPTAG", attrREPTAG);
      rootSCA.addAttribute("SCID", attrSCID);
      rootSCA.addAttribute("RC", "11104");
      SCSPUtils.addElement(rootSCA, "DS", ds);
      String dataStr = "<Service_Information><Service_Result_Code>11</Service_Result_Code></Service_Information>";
      try
      {
        SCSPUtils.addElement(rootSCA, "DATA", Comutils.parseText(dataStr).getRootElement());
      } catch (Exception e1) {
        logger.warn(e1.toString());
      }
      sendMsg(session, rootSCA);
      return;
    }
  }

  public void handleSCA(IoSession session, Element answerRoot, SCSPMessage req)
  {
    CallParam callParam = (CallParam)req.getStateObject();
    Message request = (Message)callParam.getRequest();
    Message answerMsg = DccAvpHelper.genAnswerForReq(request);

    int resultCode = convertSCA2CCA(answerRoot, answerMsg, callParam.getServiceContextId());
    if (resultCode != 0) {
      callParam.setRetCode(resultCode);
      answerMsg.add(DccAvpHelper.createServiceResultCodeAVPs(resultCode));
    }
    callParam.setResponse(answerMsg);
    callParam.getAsynHandler().onCallResult(callParam);
  }

  public static XmlMessage createERRAnwser(XmlMessage request, int retCode, String errMsg)
  {
    XmlMessage ack = new XmlMessage(false);
    ack.setMID(request.getMID());
    ack.setRTT(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(Long.valueOf(System.currentTimeMillis())));
    ack.setRC(Integer.toString(retCode));
    ack.setDS(errMsg);

    return ack;
  }

  public void start()
  {
    logger.info("start scsp server node ... ");

    int port = 4876;
    String hostAddress = "0.0.0.0";
    try
    {
      URI uri = new URI(this.scspURL);
      port = uri.getPort();
      hostAddress = uri.getHost();
    } catch (URISyntaxException e) {
      logger.warn("URI parse failed:" + this.scspURL + ",node=" + this.hostId);
    }

    setHostConf(this.hostId, hostAddress, port, this.userName, "");

    startAsServer();
  }

  private void loadConfConnectParams()
  {
  }

  public int convertSCA2CCA(Element rootSCA, Message msgCCA, String scid)
  {
    int resultCode = 0;
    if (rootSCA == null) {
      return 3002;
    }
    String RC4SCA = null;
    try {
      RC4SCA = SCSPUtils.parseField(rootSCA, "RC", false);
    } catch (FieldNotExistException e1) {
      logger.warn("FieldNotExistException:" + e1.getFieldName());
      return 5005;
    }
    if (RC4SCA != null) {
      try {
        resultCode = Integer.parseInt(RC4SCA);
      } catch (NumberFormatException e1) {
        logger.warn("NumberFormatException:" + RC4SCA);
        return 5004;
      }
    }
    if (resultCode != 0) {
      return resultCode;
    }
    Element e = null;

    e = rootSCA.element("DATA");
    if (e == null) {
      logger.warn("no DATA!" + rootSCA.asXML());
    }
    ProtocalConvertResult respConvRst = DataExchangerImpl.getInstance().convertToCCAResult(scid, e);

    if (respConvRst.getRetCode() != 0) {
      return 11107;
    }
    DccAvpHelper.addBusinessAVPs((AVP)respConvRst.getResult(), msgCCA);

    return resultCode;
  }

  public void stop()
  {
  }

  public Element createSCA(SgwQueryReq sgwQueryReq)
  {
    Element rootSCA = DocumentHelper.createElement("SCA");
    rootSCA.addAttribute("MID", sgwQueryReq.getMID());
    rootSCA.addAttribute("SCID", sgwQueryReq.getSCID());
    rootSCA.addAttribute("RC", "11104");
    return rootSCA;
  }

  public SGWChannel getSGWChannel()
  {
    return null;
  }

  public int sendRequest(CallParam callParam)
  {
    Message request = (Message)callParam.getRequest();

    AVP sgwRootAVP = DccAvpHelper.createSGWRootAVPFromMessage(request);
    ProtocalConvertResult ccrConvertRst = DataExchangerImpl.getInstance().convertFromCCRRequest(callParam.getServiceContextId(), 
      sgwRootAVP);
    if (ccrConvertRst.getRetCode() != 0) {
      callParam.setRetCode(ccrConvertRst.getRetCode());
      callParam.setResultMsg(ccrConvertRst.getErrMsg());
      callParam.getAsynHandler().onCallResult(callParam);
      return -1;
    }

    Node toNode = callParam.getToNode();

    Element rootSCR = 
      DocumentHelper.createElement("SCR");
    rootSCR.addAttribute("MID", 
      callParam.getSessionId());
    rootSCR.addAttribute("UID", 
      toNode.getHostId());
    rootSCR.addAttribute("PWD", 
      toNode.getPassword());
    rootSCR.addAttribute("SN", toNode.getHostId());
    rootSCR.addAttribute("SCID", 
      callParam.getServiceContextId());

    SCSPUtils.addElement(rootSCR, "DATA", 
      (Element)ccrConvertRst.getResult());

    sendRequest(toNode.getHostId(), rootSCR, callParam);
    return 0;
  }

  public void addPersist(Node node)
  {
  }

  public void deletePersist(Node node)
  {
  }

  public int getNodeSendQueueSize(String nodeHostId)
  {
    return 0;
  }

  public int getThreadPoolActiveCount()
  {
    return 0;
  }
}